#include "aithread.h"
#include <qdebug.h>
#include <cmath>
#include <QDebug>
#define NOTSIDE(a) ((a)!=0 && (a)!=5)
static int dr[]={0,1,-1,-1,0,-1,1,1,0};
static double v[6][6]={{.8,1  ,1  ,1  ,1  ,.8},
				{ 1,1  ,1.1,1.1,1  , 1},
				{ 1,1.1,1  ,1  ,1.1, 1},
				{ 1,1.1,1  ,1  ,1.1, 1},
				{ 1,1  ,1.1,1.1,1  , 1},
				{.8,1  ,1  ,1  ,1  ,.8}};
double AIThread::maxValue;
Steps AIThread::s;
QReadWriteLock AIThread::lock;
AIThread::AIThread(bool b,int d,QList<Steps>& l1):Gamer(b),depth(d),l(l1)
{
}
AIThread::~AIThread()
{
}

void AIThread::go()
{
	mutex.lock();
	x=0,xm=xm2=x2=0;
	double z=0;
	double m;
	double v;
	total=0;
	QList<Steps>::iterator itr;
	for (itr=l.begin();itr!=l.end();itr++)
	{
		lock.lockForRead();
		m=maxValue;
		lock.unlock();
		a.move((*itr).si(),(*itr).sj(),(*itr).ei(),(*itr).ej());
		v=-search(depth,-1/z,-m,1-bw);
		a.umove((*itr).si(),(*itr).sj(),(*itr).ei(),(*itr).ej(),(*itr).e());

		if(v>m)
		{
			m=v;
			lock.lockForWrite();
			if(m>maxValue)
			{
				qDebug()<<"write";
				maxValue=m;
				s=(*itr);
			}else
			{
				m=maxValue;
			}
			lock.unlock();
			//s=*itr;
		}
	}
	//emit move(s.si(),s.sj(),s.ei(),s.ej());
	//qDebug()<<"total="<<total;
	//qDebug()<<"val="<<m;
	//qDebug()<<"xmax="<<xm<<"xmax2="<<xm2;
	mutex.unlock();
}
double AIThread::val(bool b)
{
	total++;
	if(x2>xm2) xm2=x2;
	double t[3];//={0,0,0};
	t[1]=a.getVal(1);
	t[2]=a.getVal(2);
	/*int i,j;
	for(i=0;i<6;i++)
		for(j=0;j<6;j++)
			t[a.get(i,j)]+=v[i][j];*/
	return t[1+b]-t[2-b]-12*(1/(t[1+b]+1e-4)-1/(t[2-b]+1e-4));
}
void AIThread::expend(QList<Steps> &l1, bool b,int &t1,bool r)
{
	t1=0;
	int i,j,ei,ej,f,k;
	QList<Steps> l2;
	if(!r)
	{
		for(k=0;a.getc(k,b,i,j);k++)
			//if(a.get(i,j)==b+1)
			{
				if(NOTSIDE(i))
				{
					a.eat(i,j,0,1,ei,ej);
					if(ei>=0)
					{
						l1.append(Steps(i,j,ei,ej,1));
						t1++;
					}
					a.eat(i,j,0,-1,ei,ej);
					if(ei>=0)
					{
						l1.append(Steps(i,j,ei,ej,1));
						t1++;
					}
				}
				if(NOTSIDE(j))
				{
					a.eat(i,j,1,0,ei,ej);
					if(ei>=0)
					{
						l1.append(Steps(i,j,ei,ej,1));
						t1++;
					}
					a.eat(i,j,-1,0,ei,ej);
					if(ei>=0)
					{
						l1.append(Steps(i,j,ei,ej,1));
						t1++;
					}
				}
				for(f=0;f<8;f++)
				{
					if(a.get(i+dr[f],j+dr[f+1])==0)
							l2.append(Steps(i,j,i+dr[f],j+dr[f+1],0));
				}
			}
	}else
	{
		for(k=0;a.getRandC(k,b,i,j);k++)
			//if(a.get(i,j)==b+1)
			{
				if(NOTSIDE(i))
				{
					a.eat(i,j,0,1,ei,ej);
					if(ei>=0)
					{
						l1.append(Steps(i,j,ei,ej,1));
						t1++;
					}
					a.eat(i,j,0,-1,ei,ej);
					if(ei>=0)
					{
						l1.append(Steps(i,j,ei,ej,1));
						t1++;
					}
				}
				if(NOTSIDE(j))
				{
					a.eat(i,j,1,0,ei,ej);
					if(ei>=0)
					{
						l1.append(Steps(i,j,ei,ej,1));
						t1++;
					}
					a.eat(i,j,-1,0,ei,ej);
					if(ei>=0)
					{
						l1.append(Steps(i,j,ei,ej,1));
						t1++;
					}
				}
				for(f=0;f<8;f++)
				{
					if(a.get(i+dr[f],j+dr[f+1])==0)
							l2.append(Steps(i,j,i+dr[f],j+dr[f+1],0));
				}
			}
	}
	l1.append(l2);
}
double AIThread::search(double d,double alpha,double beta,bool b)
{
	//qDebug()<<"d="<<d;
	//qDebug()<<"x="<<x<<"d="<<d;
	if(a.gett(b+1)==0) return val(b)+x/10;
	if (d<=depth/5)
	{
		//qDebug()<<"v"<<val();
		if(x>xm) xm=x;
		return search2(depth/5,alpha,beta,b);
	}
	QList<Steps> l1;
	int t1,t2;
	expend(l1,b,t1);double v;
	t2=l1.length()-t1;
	QList<Steps>::iterator itr;
	for (itr=l1.begin();itr!=l1.end();itr++)
	{
		x++;
		a.move((*itr).si(),(*itr).sj(),(*itr).ei(),(*itr).ej());
		if((*itr).e())
			v=-search(d-log(t1*2),-beta,-alpha,1-b);
		else
			v=-search(d-log(t2*2),-beta,-alpha,1-b);
		//v=-search(d-log(t1+t2),-beta,-alpha,1-b);
		x--;
		a.umove((*itr).si(),(*itr).sj(),(*itr).ei(),(*itr).ej(),(*itr).e());
		if (v >= beta)
		{
			return v;
		}
		if (v > alpha)
		{
			alpha = v;
		}
	}
	 return alpha;
}
double AIThread::search2(double d, double alpha, double beta, bool b)
{
	if(a.gett(b+1)==0) return val(b)+x/10;
	if (d<=0)
	{
		return val(b);
	}
	QList<Steps> l1;
	expend2(l1,b);
	if(l1.isEmpty()) return val(b);
	double v;
	int t1=l1.length();
	QList<Steps>::iterator itr;
	for (itr=l1.begin();itr!=l1.end();itr++)
	{
		x2++;
		a.move((*itr).si(),(*itr).sj(),(*itr).ei(),(*itr).ej());
		v=-search2(d-log(t1),-beta,-alpha,1-b);
		x2--;
		a.umove((*itr).si(),(*itr).sj(),(*itr).ei(),(*itr).ej(),(*itr).e());
		if (v >= beta)
		{
			return v;
		}
		if (v > alpha)
		{
			alpha = v;
		}
	}
	 return alpha;
}
void AIThread::expend2(QList<Steps> &l1, bool b)
{
	int i,j,ei,ej,f,k;
	for(k=0;a.getc(k,b,i,j);k++)
			if(a.get(i,j)==b+1)
			{
				if(NOTSIDE(i))
				{
					a.eat(i,j,0,1,ei,ej);
					if(ei>=0)
						l1.append(Steps(i,j,ei,ej,1));
					a.eat(i,j,0,-1,ei,ej);
					if(ei>=0)
						l1.append(Steps(i,j,ei,ej,1));
				}
				if(NOTSIDE(j))
				{
					a.eat(i,j,1,0,ei,ej);
					if(ei>=0)
						l1.append(Steps(i,j,ei,ej,1));
					a.eat(i,j,-1,0,ei,ej);
					if(ei>=0)
						l1.append(Steps(i,j,ei,ej,1));
				}
			}
}
